package mx.itesm.demojpct_ae;

import java.lang.reflect.Field;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLSurfaceView;

import com.threed.jpct.Camera;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Object3D;
import com.threed.jpct.RGBColor;
import com.threed.jpct.World;
import com.threed.jpct.util.MemoryHelper;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;

public class Juego extends Activity {
	private static Juego main; // Un s�lo juego
	private GLSurfaceView mGLView; // Contenedor para dibujar
	private Renderer renderer; // El objeto que hace los trazos
	private FrameBuffer buffer; // Buffer para trazar
	private World mundo; // Un escenario de nuestro juego
	private RGBColor colorFondo; // Color de fondo :)
	private Camera camara;

	// Agregamos objetos en el mundo
	private Object3D objPista;
	private Object3D objAvion;

	// Para guardar el desplazamiento del touch (pixeles)
	private float xPos = -1;
	private float yPos = -1;
	// Longitud de desplazamiento
	private float offsetHorizontal = 0; // Izquierda-derecha
	private float offsetVertical = 0; // Arriba-abajo
	
	// Contador de FPS
	private int fps;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		if (main != null) { // Si ya existe el juego, copiar sus campos
			copiar(main);
		}
		super.onCreate(savedInstanceState);
		mGLView = new GLSurfaceView(getApplicationContext());
		
		// S�lo por compatibilidad con dispositivos 1.6
		/*
		mGLView.setEGLConfigChooser(new GLSurfaceView.EGLConfigChooser() { // Configuraci�n
			public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
				int[] atributos = new int[] { EGL10.EGL_DEPTH_SIZE, 16,
						EGL10.EGL_NONE };
				EGLConfig[] configs = new EGLConfig[1];
				int[] resultado = new int[1];
				egl.eglChooseConfig(display, atributos, configs, 1, resultado);
				return configs[0];
			}
		});
		*/

		renderer = new Renderer();
		mGLView.setRenderer(renderer);
		setContentView(mGLView);
	}

	@Override
	protected void onPause() {
		super.onPause();
		mGLView.onPause();
	}

	@Override
	protected void onResume() {
		super.onResume();
		mGLView.onResume();
	}

	@Override
	protected void onStop() {
		super.onStop();
	}

	private void copiar(Object src) {
		try {
			Field[] fs = src.getClass().getDeclaredFields();
			for (Field f : fs) {
				f.setAccessible(true);
				f.set(this, f.get(src));
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	// Hay un evento de touch en la pantalla
	@Override
	public boolean onTouchEvent(MotionEvent evento) {
		
		if (evento.getAction() == MotionEvent.ACTION_DOWN) { // Inicia touch
			xPos = evento.getX();
			yPos = evento.getY();
			return true; // Significa que el evento ha sido atendido
		}

		if (evento.getAction() == MotionEvent.ACTION_UP) { // Termina touch
			xPos = -1;
			yPos = -1;
			offsetHorizontal = 0;
			offsetVertical = 0;
			return true;
		}

		if (evento.getAction() == MotionEvent.ACTION_MOVE) { // Drag
			float xd = evento.getX() - xPos;
			float yd = evento.getY() - yPos;

			xPos = evento.getX();
			yPos = evento.getY();

			offsetHorizontal = xd / -100f;
			offsetVertical = yd / -100f;
			return true;
		}

		return super.onTouchEvent(evento);
	
	}

	class Renderer implements GLSurfaceView.Renderer {
		
		private long tiempo = System.currentTimeMillis();

		@Override
		public void onDrawFrame(GL10 gl) { // ACTUALIZACIONES

			// ACTUALIZAR camara

			if (offsetVertical != 0) {
				camara.moveCamera(Camera.CAMERA_MOVEDOWN, offsetVertical);
				offsetVertical = 0;
			} else {
				objAvion.translate(0, 0, 0.1f);
				camara.moveCamera(Camera.CAMERA_MOVEIN, 0.1f);
			}

			if (offsetHorizontal != 0) {
				camara.moveCamera(Camera.CAMERA_MOVERIGHT, offsetHorizontal);
				offsetHorizontal = 0;
			}

			// final
			buffer.clear(colorFondo); // Borrar el buffer
			mundo.renderScene(buffer);// C�lculos sobre los objetos a dibujar
			mundo.draw(buffer); // Redibuja todos los objetos
			buffer.display(); // Actualiza en pantalla
			
			// Contador de FPS
			if (System.currentTimeMillis() - tiempo > 1000) {
				Log.d("FPS", fps + "fps");
				tiempo = System.currentTimeMillis();
				fps = 0;
			}
			
			fps++;
		}

		@Override
		public void onSurfaceChanged(GL10 gl, int width, int height) {

			if (buffer != null) {
				buffer.dispose();
			}

			buffer = new FrameBuffer(gl, width, height);

			if (main == null) {

				mundo = new World();
				mundo.setAmbientLight(128, 128, 128);
				colorFondo = new RGBColor(0x7F, 0x7F, 0x7F);

				// Carga la pista
				objPista = Modelo.cargarModeloMTL(getBaseContext(),
						"pista.obj", "pista.mtl", 1);
				// Rotarlo 180�
				objPista.rotateX(3.141592f);
				mundo.addObject(objPista);

				// Carga el avi�n
				objAvion = Modelo.cargarModeloMTL(getBaseContext(),
						"avion.obj", "avion.mtl", 1);
				// Mueve el avi�n fuera de la pista
				objAvion.translate(0, 0, -150);
				// Lo rota para que quede en la posici�n correcta
				objAvion.rotateY(3.141592f);
				objAvion.rotateX(3.141592f);
				mundo.addObject(objAvion);

				// Para manejar la c�mara
				camara = mundo.getCamera();
				camara.moveCamera(Camera.CAMERA_MOVEOUT, 160); // Queda un
																// "poco" atr�s
																// del avi�n
				camara.moveCamera(Camera.CAMERA_MOVEUP, 3);

				MemoryHelper.compact();
				if (main == null) {
					main = Juego.this;
				}
			}
		}

		@Override
		public void onSurfaceCreated(GL10 gl, EGLConfig config) {
		}

	}
}